Imports System.Windows.Forms
Imports System.Drawing

<System.ComponentModel.DefaultEvent("CheckStateChanged")> Public Class CheckBox3D
    Inherits Control
    Private TLC As Bitmap = My.Resources._01
    Private TRC As Bitmap = My.Resources._02
    Private BLC As Bitmap = My.Resources._03
    Private BRC As Bitmap = My.Resources._04
    Private ColMat As Single()() = {New Single() {100, 0, 0, 0, 0}, New Single() {0, 100, 0, 0, 0}, New Single() {0, 0, 100, 0, 0}, New Single() {0, 0, 0, 100, 0}, New Single() {0, 0, 0, 0, 100}}
    Private BasePic As Bitmap
    Private HiUpPic As Bitmap
    Private HiDownPic As Bitmap
    Private NormalDownPic As Bitmap
    Private NormalUpPic As Bitmap
    Private Hi As Boolean = False
    Private down As Boolean = False
    Private m_HiColor As Color = Color.Gray
    Private m_NormalColor As Color = Color.DarkGray

    Private TCol As Color = Color.Black
    Private M_Op As Integer = 100
    Private TOX As Integer = 0
    Private TOY As Integer = 0
    Private M_LEDImage As Bitmap
    Delegate Sub RefreshMeCallback()
    Private M_Checked As Boolean = False
    Private M_ShowLED As Boolean = True
    Private M_LEDSize As Integer = 10

    Private m_OnColor As Color = Color.LimeGreen
    Private m_OffColor As Color = Color.DarkGreen
    Private m_OnText As String = "On"
    Private m_OffText As String = "Off"
    Public Event CheckStateChanged(ByVal CurrentState As Boolean)

    Public Enum ButtonImageModeConst
        None = 0
        Center = 1
        Resize = 2
    End Enum

    Private Sub CheckBox3D_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
        If M_Checked Then
            M_Checked = False
        Else
            M_Checked = True
        End If
        RaiseEvent CheckStateChanged(M_Checked)
        Me.Refresh()
    End Sub
    Private Sub Button3D_ForeColorChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ForeColorChanged
        UpdateButton()
    End Sub

    Private Sub Button3D_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
        'down = True
        'Me.Refresh()
    End Sub

    Private Sub Button3D_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseEnter
        Hi = True
        Me.Refresh()

    End Sub

    Private Sub Button3D_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseLeave
        Hi = False
        Me.Refresh()
    End Sub

    Private Sub Button3D_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
        'down = False
        'Me.Refresh()
    End Sub
    Private Sub button2_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Dim G As Graphics = e.Graphics
        Dim W As Integer
        Dim H As Integer
        W = NormalUpPic.Width
        H = NormalUpPic.Height
        If Hi = True Then
            If M_Checked = True Then
                G.DrawImage(HiDownPic, 0, 0, W, H)
            Else
                G.DrawImage(HiUpPic, 0, 0, W, H)
            End If
        Else
            If M_Checked = True Then
                G.DrawImage(NormalDownPic, 0, 0, W, H)
            Else
                G.DrawImage(NormalUpPic, 0, 0, W, H)
            End If
        End If
        If M_ShowLED = True Then
            M_LEDImage = New Bitmap(M_LEDSize + 2, M_LEDSize + 2, Imaging.PixelFormat.Format32bppArgb)
            Dim LEDG As Graphics = Graphics.FromImage(M_LEDImage)
            LEDG.Clear(Color.Transparent)
            Dim LBrush As SolidBrush
            If M_Checked Then
                LBrush = New SolidBrush(m_OnColor)
            Else
                LBrush = New SolidBrush(m_OffColor)
            End If
            LEDG.FillEllipse(LBrush, 1, 1, M_LEDSize, M_LEDSize)
            LEDG.DrawEllipse(Pens.Black, 1, 1, M_LEDSize, M_LEDSize)

            Dim BIX As Integer
            Dim BIY As Integer
            If M_Checked = False Then
                BIX = (TOX - 1)
                BIY = ((Me.Height / 2) - (M_LEDImage.Height / 2) - 2)
            Else
                BIX = (TOX + 1)
                BIY = ((Me.Height / 2) - (M_LEDImage.Height / 2) + 0)
            End If
            G.DrawImage(M_LEDImage, BIX, BIY)
        End If

        Dim X As Integer
        Dim Y As Integer
        Dim m_Txt As String
        If M_Checked Then
            m_Txt = m_OnText
        Else
            m_Txt = m_OffText
        End If
        X = TOX + M_LEDSize + 1
        Y = (Me.Height - G.MeasureString(m_Txt, Me.Font).Height) / 2
        Dim BR As New SolidBrush(TCol)
        If Me.Text > "" Then
            If M_Checked = False Then
                G.DrawString(m_Txt, Me.Font, BR, X - 1 + TOX, Y - 1 + TOY)
            Else
                G.DrawString(m_Txt, Me.Font, BR, X + 1 + TOX, Y + 1 + TOY)
            End If
        End If

        BR.Dispose()
    End Sub
    Private Sub DrawBase()
        If Me.Height < 1 Then Me.Height = 10
        If Me.Width < 1 Then Me.Width = 10
        Dim BP As New Bitmap(Me.Width, Me.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
        TLC.MakeTransparent(Color.White)
        TRC.MakeTransparent(Color.White)
        BLC.MakeTransparent(Color.White)
        BRC.MakeTransparent(Color.White)
        Dim g As Graphics = Graphics.FromImage(BP)
        Dim X As Integer
        Dim Y As Integer
        Dim W As Integer = TLC.Width / 3
        Dim H As Integer = TLC.Height / 3
        Dim r As New Rectangle(W / 2, H / 2, Me.Width - W, Me.Height - H)
        Dim Col As Color = BRC.GetPixel(0, 0)
        Dim BR As New SolidBrush(Col)
        g.Clear(Color.Transparent)
        g.FillRectangle(BR, r)
        For X = W To (BP.Width - W)
            g.DrawImage(TRC, X, 0, W, H)
            g.DrawImage(BRC, X, BP.Height - H, W, H)
        Next X
        For Y = H To (BP.Height - H)
            g.DrawImage(BLC, 0, Y, W, H)
            g.DrawImage(BRC, BP.Width - W, Y, W, H)
        Next
        g.DrawImage(BLC, 0, BP.Height - H, W, H)
        g.DrawImage(TLC, 0, 0, W, H)
        BR.Dispose()
        BasePic = New Bitmap(BP)
        BP.Dispose()
    End Sub
    Private Function Colorize(ByVal Col As Color) As Bitmap
        Dim OutPic As New Bitmap(BasePic.Width, BasePic.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
        Dim R As Double
        Dim G As Double
        Dim B As Double
        Dim S As Double = 100 / 255
        Dim Op As Double
        R = (Col.R * S) / 100
        G = (Col.G * S) / 100
        B = (Col.B * S) / 100
        Op = M_Op / 100
        Dim Mat As Single()() = { _
                New Single() {R, 0, 0, 0, 0}, _
                New Single() {0, G, 0, 0, 0}, _
                New Single() {0, 0, B, 0, 0}, _
                New Single() {0, 0, 0, Op, 0}, _
                New Single() {0, 0, 0, 0, 1}}
        Dim colorMatrix As New System.Drawing.Imaging.ColorMatrix(Mat)
        ' Create an ImageAttributes object and set its color matrix.
        Dim imageAtt As New System.Drawing.Imaging.ImageAttributes()
        imageAtt.SetColorMatrix(colorMatrix, System.Drawing.Imaging.ColorMatrixFlag.Default, System.Drawing.Imaging.ColorAdjustType.Bitmap)
        imageAtt.SetColorKey(System.Drawing.Color.Black, System.Drawing.Color.White)
        Dim r1 As RectangleF
        r1.X = 0
        r1.Y = 0
        r1.Width = OutPic.Width
        r1.Height = OutPic.Height
        Dim r2 As RectangleF
        r2.X = 0
        r2.Y = 0
        r2.Width = OutPic.Width
        r2.Height = OutPic.Height
        Dim Grap As Graphics = Graphics.FromImage(OutPic)
        Dim brush3 As New TextureBrush(BasePic, r1, imageAtt)
        Grap.FillRectangle(brush3, r2)
        Grap.Dispose()
        brush3.Dispose()
        Return OutPic
    End Function
    Private Function Flip(ByVal Bmp As Bitmap) As Bitmap
        Dim FBmp As New Bitmap(Bmp)
        FBmp.RotateFlip(RotateFlipType.Rotate180FlipNone)
        Return FBmp
    End Function
    Private Sub Button3D_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        UpdateButton()
    End Sub
    Public Property HiLiteColor() As Color
        Get
            Return m_HiColor
        End Get
        Set(ByVal value As Color)
            m_HiColor = value
            UpdateButton()
        End Set
    End Property
    Public Property NormalColor() As Color
        Get
            Return m_NormalColor
        End Get
        Set(ByVal value As Color)
            m_NormalColor = value
            UpdateButton()
        End Set
    End Property
    Public Property TextColor() As Color
        Get
            Return TCol
        End Get
        Set(ByVal value As Color)
            TCol = value
            Me.Refresh()

        End Set
    End Property

    Public Sub New()
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
        Me.BackColor = Color.Transparent
    End Sub
    Public Property Opacity() As Integer
        Get
            Return M_Op
        End Get
        Set(ByVal value As Integer)
            M_Op = value
            Me.Refresh()
        End Set
    End Property
    Public Property OffsetX() As Integer
        Get
            Return TOX
        End Get
        Set(ByVal value As Integer)
            TOX = value
            Me.Refresh()
        End Set
    End Property
    Public Sub UpdateButton()
        DrawBase()
        NormalUpPic = Colorize(m_NormalColor)
        NormalDownPic = Flip(NormalUpPic)
        HiUpPic = Colorize(m_HiColor)
        HiDownPic = Flip(HiUpPic)

        Me.Refresh()
    End Sub
    Private Sub RefreshMe()
        If Me.InvokeRequired Then
            Dim d As New RefreshMeCallback(AddressOf RefreshMe)
            Me.Invoke(d)
        Else
            Me.Refresh()
        End If
    End Sub
    Public Property Checked() As Boolean
        Get
            Return M_Checked
        End Get
        Set(ByVal value As Boolean)
            M_Checked = value
            Me.Refresh()
        End Set
    End Property
    Public Property ShowLED() As Boolean
        Get
            Return M_ShowLED
        End Get
        Set(ByVal value As Boolean)
            M_ShowLED = value
            Me.Refresh()
        End Set
    End Property
    Public Property LEDSize() As Integer
        Get
            Return M_LEDSize
        End Get
        Set(ByVal value As Integer)
            M_LEDSize = value
            Me.Refresh()
        End Set
    End Property
    Public Property LEDOnColor() As Color
        Get
            Return m_OnColor
        End Get
        Set(ByVal value As Color)
            m_OnColor = value
            Me.Refresh()
        End Set
    End Property
    Public Property LEDOffColor() As Color
        Get
            Return m_OffColor
        End Get
        Set(ByVal value As Color)
            m_OffColor = value
            Me.Refresh()
        End Set
    End Property
    Public Property OnText() As String
        Get
            Return m_OnText
        End Get
        Set(ByVal value As String)
            m_OnText = value
            Me.Refresh()
        End Set
    End Property
    Public Property OffText() As String
        Get
            Return m_OffText
        End Get
        Set(ByVal value As String)
            m_OffText = value
            Me.Refresh()
        End Set
    End Property
End Class
